package com.hmdp.utils;

import org.springframework.core.io.ClassPathResource;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.core.script.DefaultRedisScript;
import org.springframework.data.redis.core.script.RedisScript;

import java.util.Collections;
import java.util.UUID;
import java.util.concurrent.TimeUnit;

public class SimpleRedisLock implements ILock{


    private String name;
    private StringRedisTemplate stringRedisTemplate;
    private final String lock_prefix = "lock:";
    //线程id是递增的，两个不同的服务可能会产生同一个个线程id，所以需要加一个UUID来保证不同服务的每个线程的表示都不同
    private final String UUID_prefix = UUID.randomUUID().toString();
    private static DefaultRedisScript<Long> REDIS_SCRIPT;

    static {
        /**
         * luna资源放在Resource目录下，通过spring提供的ClassPathResource可以很方便的定位
         * 同时作为要IO的操作，应该一开始就初始化好，无疑放在今天代码块里完成初始化
         */
        REDIS_SCRIPT = new DefaultRedisScript<>();
        REDIS_SCRIPT.setLocation(new ClassPathResource("unlock.lua"));
        REDIS_SCRIPT.setResultType(Long.class);
    }

    public SimpleRedisLock(String name, StringRedisTemplate stringRedisTemplate) {
        this.name = name;
        this.stringRedisTemplate = stringRedisTemplate;
    }

    @Override
    public boolean tryLock(long timeoutSec) {
        //线程id作为value
        long threadId = Thread.currentThread().getId();
        Boolean success = stringRedisTemplate.opsForValue().setIfAbsent(lock_prefix + name, UUID_prefix + threadId,
                timeoutSec, TimeUnit.SECONDS);
        return Boolean.TRUE.equals(success);
    }

    @Override
    public void unlock() {
        stringRedisTemplate.execute(REDIS_SCRIPT, Collections.singletonList(lock_prefix + name),
                UUID_prefix + Thread.currentThread().getId());
    }
}
